package shape;

/**
 * @author Zach Turk
 * @author Ken "David" McClain
 */

import javax.media.opengl.*;

import main.SceneGraphNode;
import physics.*;

public class Compound extends PhysicsObject {
	/** Serial ID */
	private static final long serialVersionUID = 8236949071487970798L;

	public class Renderable extends SceneGraphNode {
		
		/** Serial ID */
		private static final long serialVersionUID = 8140009719497988247L;

		public Renderable() {
			super(true);
			scale = size;
		}
		
		public Renderable(boolean pickable) {
			super(pickable);
			scale = size;
		}
		
		public void renderGeometry(GLAutoDrawable drawable) {
			GL2 gl = drawable.getGL().getGL2();
			gl.glPushMatrix();
			gl.glScalef(scale, scale, 0);
			for (int i = 0; i < objects.length; i++) {
				PhysicsObject o = objects[i];
				if (o == null) 
					continue;
				
				gl.glPushMatrix();
				gl.glTranslatef(offsets[i].x, offsets[i].y, 0);
				o.renderable.renderGeometry(drawable);
				gl.glPopMatrix();
			}
			gl.glPopMatrix();
		}
	}
	
	private PhysicsObject[] objects = new PhysicsObject[3];
	private Vector2f[] offsets = new Vector2f[3];
	
	public float size;
	
	public Compound(float s) {
		this.size = s;
		this.orientation = 0.0f;
		renderable = new Renderable(true);
		this.centerOfMass = new Vector2f(0, 0f);
		
		PhysicsObject o = new Circle(s);
		o.inverseMass = 1 / 2f;
		o.inverseMomentOfInertia = 1 / (float)(Math.PI * Math.pow(s, 4) / 4);
		objects[0] = o;
		offsets[0] = new Vector2f(0, 0.0f);
		
		PhysicsObject sq = new Square(1);
		sq.inverseMass = 1f / 4;
		sq.inverseMomentOfInertia *= sq.inverseMass;
		objects[1] = sq;
		offsets[1] = new Vector2f(-0.5f, 1f);
		
		sq = new Square(1);
		sq.inverseMass = 1f / 4;
		sq.inverseMomentOfInertia *= sq.inverseMass;
		objects[2] = sq;
		offsets[2] = new Vector2f(-0.5f, -2f);
		
		// MOI for our composite object should be the sum of the MOI of the sub objects.
		this.inverseMomentOfInertia = 0; //(float)( 1 / (objects[0].inverseMomentOfInertia * Math.pow(offsets[0].y, 2) + objects[1].inverseMomentOfInertia * Math.pow(offsets[1].y, 2) + objects[2].inverseMomentOfInertia * Math.pow(offsets[2].y, 2)));
	}
	
	public PhysicsObject[] getObjects() {
		PhysicsObject[] objs = new PhysicsObject[3];
		for (int i = 0; i < 3; i++) {
			
			if (objects[i] == null)
				continue;
			
			if (objects[i] instanceof Square)
				objs[i] = new Square(1);
			else
				objs[i] = new Circle(1);
			
			objs[i].inverseMass = objects[i].inverseMass;
			objs[i].inverseMomentOfInertia = objects[i].inverseMomentOfInertia;
			objs[i].centerOfMass = new Vector2f(super.centerOfMass);
			objs[i].position.x   = super.position.x + (float) Math.sin(super.orientation)*offsets[i].x;
			objs[i].position.y   = super.position.y + (float) Math.cos(super.orientation)*offsets[i].y;
			objs[i].acceleration = new Vector2f(super.acceleration);
			objs[i].velocity     = new Vector2f(super.velocity);
			objs[i].angularVelocity = super.angularVelocity;
			objs[i].orientation  = super.orientation;
		}
		return objs;
	}
}